package com.example.score.controller;

import com.example.score.dao.SportsmanRepository;
import com.example.score.entity.*;
import com.example.score.score.ConfirmSocket;
import com.example.score.score.JudgeSocket;
import com.example.score.score.SocketScore;
import com.example.score.score.ViewSocket;
import com.example.score.utils.ThreadManager;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Lazy;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@RestController
public class TempController {
    public static Set<Sportsman> sets = new HashSet<>(100);

    @Resource
    private SportsmanRepository sportsmanRepository;

    private static final HashMap<String, Sportsman> storageTask = new HashMap<>(10);

    @Resource
    private ConfirmSocket confirmSocket;

    @Resource
    ViewSocket viewSocket;

    @Resource
    private JudgeSocket judgeSocket;

    @Resource
    @Lazy
    private SocketScore socketScore;


    @PostMapping("/input")
    public ResponseEntity<String> inputData(@RequestBody List<Sportsman> datas) {
        sportsmanRepository.saveAll(datas);
        return ResponseEntity.ok("ok");
    }

    @GetMapping("/getgroups")
    public ResponseEntity<List<Group>> getGroups() {
        List<Sportsman> sportsmanList = sportsmanRepository.findAll();
        List<Group> groups = new ArrayList<>(sportsmanList.size());
        for (Sportsman sportsman : sportsmanList) {
            Group group = new Group(sportsman.getGroupName(), Math.toIntExact(sportsman.getGroupIndex()), 1, sportsman.getArea(), sportsman.getSportData());
            boolean contains = false;
            for (Group value : groups) {
                if (value.equals(group)) {
                    value.memberIncrement();
                    contains = true;
                    break;
                }
            }
            if (!contains) {
                groups.add(group);
            }
        }
        return ResponseEntity.ok(groups);
    }

    @GetMapping("/contest/over")
    public ResponseEntity<String> contestOver(HttpServletRequest request) {
        String refereeId = request.getHeader("Token");
        ThreadManager.threadPool.submit(() -> {
            try {
                Thread.sleep(15000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            viewSocket.show(new ViewMode("-1", null), refereeId);
        });
        return ResponseEntity.ok("ok");
    }

    @PostMapping("/score/confirm/{uuid}")
    public ResponseEntity<String> confirmScoring(@PathVariable Long uuid) {
        Optional<Sportsman> sportsmanOptional = sportsmanRepository.findById(uuid);
        if (sportsmanOptional.isPresent()) {
            Sportsman entity = sportsmanOptional.get();
            // 更新实体的属性
            entity.setStatus("已确认");
            // 保存更新后的实体
            sportsmanRepository.save(entity);
        }
        return ResponseEntity.ok("ok");
    }

    @PostMapping("/competition/start")
    public ResponseEntity<String> startCompetition(@RequestBody StartDto dto) throws IOException {
        List<Long> ids = dto.getIds();
        List<Sportsman> sportsmen = sportsmanRepository.findAllById(ids);
        for (Sportsman s : sportsmen) {
            s.setStatus("进行中");
        }
        sportsmanRepository.saveAll(sportsmen);
        socketScore.startGroup(sportsmen, dto.getRefereeId());
        // 通知展示端进行比赛信息的展示
        viewSocket.show(new ViewMode("0", sportsmen), dto.getRefereeId());
        return ResponseEntity.ok("ok");
    }

    /**
     * 获取下一组, 先通过groupName 获取所有的运动员，然后按照groupIndex 和 index（groupIndex 相同） 升序排列
     * 然后遍历，找到第一个status 为 未开始 运动员，然后返回所有与他groupIndex 相同，并且都是未开始的运动员
     *
     * @param groupName
     * @return
     */
    @GetMapping("/group/{groupName}/next")
    public ResponseEntity<List<Sportsman>> getNextGroup(@PathVariable String groupName) {
        ResponseEntity<List<Sportsman>> response = athletesByName(groupName);
        List<Sportsman> sportsmanList = response.getBody();

        if (sportsmanList == null || sportsmanList.isEmpty()) {
            return ResponseEntity.notFound().build();
        }

        // 对运动员列表按groupIndex排序，如果groupIndex相同则按index排序
        List<Sportsman> sortedSportsmanList = sportsmanList.stream()
                .sorted(Comparator.comparing(Sportsman::getGroupIndex)
                        .thenComparing(Sportsman::getIndex))
                .collect(Collectors.toList());

        // 找到第一个status为未开始的运动员
        Sportsman firstNotStarted = sortedSportsmanList.stream()
                .filter(s -> "未开始".equals(s.getStatus()))
                .findFirst()
                .orElse(null);

        if (firstNotStarted == null) {
            return ResponseEntity.status(200).body(Collections.emptyList());
        }

        // 获取所有与第一个未开始的运动员同一groupIndex的运动员
        Long firstGroupIndex = firstNotStarted.getGroupIndex();
        List<Sportsman> sameGroupNotStarted = sortedSportsmanList.stream()
                .filter(s -> s.getGroupIndex().equals(firstGroupIndex) && "未开始".equals(s.getStatus()))
                .collect(Collectors.toList());
        // 然后需要把这些运动员的状态设置为等待中
        sameGroupNotStarted.forEach(s -> {
            s.setStatus("等待中");
            sportsmanRepository.save(s);
        });

        return ResponseEntity.ok(sameGroupNotStarted);
    }


    /**
     * 把给定ID 的运动员状态重置为未开始，如果运动员的状态已经是已结束，则不重置
     * @param ids
     * @return
     */
    @PostMapping("/reset")
    public ResponseEntity<String> reset(@RequestBody List<Long> ids) {
        for (Long id : ids) {
            Optional<Sportsman> sportsmanOptional = sportsmanRepository.findById(id);
            if (sportsmanOptional.isPresent()) {
                Sportsman entity = sportsmanOptional.get();
                if (!"已结束".equals(entity.getStatus())) {
                    entity.setStatus("未开始");
                    sportsmanRepository.save(entity);
                }
            }
        }
        return ResponseEntity.ok("ok");
    }


    @GetMapping("/getAthletesName")
    public ResponseEntity<List<Sportsman>> athletesByName(String groupName) {
        log.info("获取运动员ByName：{}", groupName);
        List<Sportsman> sportsmanList = sportsmanRepository.findAll();
        List<Sportsman> groups = new ArrayList<>(sportsmanList.size());
        for (Sportsman set : sportsmanList) {
            if (set.getGroupName().equals(groupName)) {
                groups.add(set);
            }
        }
        groups.sort(Comparator.comparingLong(Sportsman::getGroupIndex));
        groups.sort(Comparator.comparingLong(Sportsman::getIndex));
        Collections.reverse(groups);
        return ResponseEntity.ok(groups);
    }

    @GetMapping("/getAthletes")
    public ResponseEntity<List<Sportsman>> athletes(Long groupIndex) {
        List<Sportsman> sportsmanList = sportsmanRepository.findAll();
        List<Sportsman> groups = new ArrayList<>(sportsmanList.size());
        for (Sportsman set : sportsmanList) {
            if (set.getGroupIndex().equals(groupIndex)) {
                groups.add(set);
            }
        }
        groups.sort(Comparator.comparingLong(Sportsman::getGroupIndex));
        Collections.reverse(groups);
        return ResponseEntity.ok(groups);
    }

    @PostMapping("/score/finalUpdate")
    public ResponseEntity<String> finalUpdate(@RequestBody Sportsman sportsman) {
        sportsman.setStatus("已确认");
        sportsmanRepository.save(sportsman);
        return ResponseEntity.ok("ok");
    }

    /**
     * 给定五个数，返回这五个数去掉最高分和最低分后的平均分
     *
     * @param goal1
     * @param goal2
     * @param goal3
     * @param goal4
     * @param goal5
     * @return
     */
    private double avg(double goal1, double goal2, double goal3, double goal4, double goal5) {
        double sum = goal1 + goal2 + goal3 + goal4 + goal5;
        double min = Math.min(Math.min(Math.min(goal1, goal2), Math.min(goal3, goal4)), goal5);
        double max = Math.max(Math.max(Math.max(goal1, goal2), Math.max(goal3, goal4)), goal5);
        return (sum - min - max) / 3;
    }

    /**
     * 裁判长提交成绩，暂存任务，成绩提交总裁判长
     * 总裁判长确认 -> 展示成绩 -> 移除任务
     * 总裁判长回退 -> 通知裁判长 -> 移除任务
     */
    @PostMapping("/submitScoring")
    public ResponseEntity<String> submitScore(HttpServletRequest request, @RequestBody Sportsman sportsman) {
        String refereeId = request.getHeader("token");
        // 更新平均成绩
        sportsman.setRefereeId(refereeId);
        String taskId = UUID.randomUUID().toString();
        storageTask.put(taskId, sportsman);
//        confirmSocket.submitScore(sportsman, taskId);
        // 直接跳过总裁确认
        confirm(taskId);
        return ResponseEntity.ok("ok");
    }

    private String avgScore(Sportsman sportsman) {
        double avgScore = (sportsman.getGoal1() + sportsman.getGoal2() + sportsman.getGoal3() + sportsman.getGoal4() + sportsman.getGoal5()) / 5;
        sportsman.setGoal(avgScore);
        return String.valueOf(avgScore);
    }

    @PostMapping("/over")
    public ResponseEntity<String> groupOver(HttpServletRequest request, @RequestBody String groupName) {
        // 获取refereeId
        String refereeId = request.getHeader("token");
        List<Sportsman> sportsmanList = sportsmanRepository.findAll();
        List<Sportsman> groupMember = new LinkedList<>();
        for (Sportsman set : sportsmanList) {
            if (set.getGroupName().equals(groupName)) {
                groupMember.add(set);
            }
        }
        // 计算平均成绩及排名
        groupMember.sort((s1, s2) -> {
            double goal = s2.getGoal() - s1.getGoal();
            return (int) goal;
        });
        List<Mode1Dto.Score> list = new ArrayList<>(groupMember.size());
        for (int i = 0; i < groupMember.size(); i++) {
            Sportsman memmber = groupMember.get(i);
            list.add(new Mode1Dto.Score(String.valueOf(i), String.valueOf(memmber.getGoal()), memmber.getSportName(), memmber.getUnit()));
        }
        viewSocket.show(new ViewMode("1", new Mode1Dto(groupName, list)), refereeId);
        return ResponseEntity.ok("ok");
    }

    public int getGroupLength(SportData data) {
        int count = 0;
        List<Sportsman> sportsmanList = sportsmanRepository.findAll();
        for (Sportsman set : sportsmanList) {
            if (set.getGroupName().equals(data.getGroupName()) && String.valueOf(data.getGroupIndex()).equals(data.getGroupIndex())) {
                count++;
            }
        }
        return count;
    }

    @GetMapping("/changeArea")
    public ResponseEntity<String> changeArea(String groupName) {
        if (groupName == null || "".equals(groupName)) {
            return ResponseEntity.badRequest().body("参数错误");
        }
        List<Sportsman> sportsmanList = athletesByName(groupName).getBody();
        assert sportsmanList != null;
        for (Sportsman sportsman : sportsmanList) {
            String area = sportsman.getArea();
            if ("1".equals(area)) {
                sportsman.setArea("2");
            } else if ("2".equals(area)) {
                sportsman.setArea("1");
            }
        }
//        sets.addAll(sportsmanList);
        return ResponseEntity.ok("ok");
    }

    @PostMapping("/confirm/{taskId}")
    public ResponseEntity<String> confirm(@PathVariable String taskId) {
        Sportsman sportsman = storageTask.get(taskId);
        if (sportsman == null) {
            return ResponseEntity.ok("success");
        }
        String refereeId = sportsman.getRefereeId();
        sportsmanRepository.save(sportsman);
        log.info("运动员{}提交成功，总裁判长确认", sportsman);
        List<Sportsman> sportsmanList = sportsmanRepository.findAll();
        // 查询出当前组的所有信息
        List<Mode1Dto.Score> list = new ArrayList<>(sportsmanList.size());
        for (Sportsman set : sportsmanList) {
            if (set.getGroupIndex().equals(sportsman.getGroupIndex()) && set.getGroupName().equals(sportsman.getGroupName())) {
                list.add(new Mode1Dto.Score("", String.valueOf(set.getGoal()), set.getSportName(), set.getUnit()));
            }
        }
        ThreadManager.threadPool.submit(() -> {
            viewSocket.show(new ViewMode("2", sportsman), refereeId);

            // TODO 设置时间间隔
            try {
                Thread.sleep(10000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            viewSocket.show(new ViewMode("1", new Mode1Dto(sportsman.getGroupName(), list)), refereeId);
        });
        socketScore.confirm(refereeId);
//        storageTask.remove(taskId);
        return ResponseEntity.ok("success");
    }

    @PostMapping("/rollback/{taskId}")
    public ResponseEntity<String> rollback(@PathVariable String taskId) {
        Sportsman sportsman = storageTask.get(taskId);
        String refereeId = sportsman.getRefereeId();
        socketScore.rollback(refereeId);

//        storageTask.remove(taskId);
        return ResponseEntity.ok("success");
    }

//    @GetMapping("/serilizable")
//    public ResponseEntity<String> deserialize() {
//        Set<Sportsman> sportsmen = null;
//        try {
//            sportsmen = SerializationUtils.deserializeSetFromFile();
//            if (sportsmen != null) {
//                sets = sportsmen;
//            }
//        } catch (Exception e) {
//            return ResponseEntity.badRequest().body("deserialize error");
//        }
//        return ResponseEntity.ok("deserialize success");
//    }
}
